﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ngram
{
    class Model1
    {
        public string process(string input)
        {
            Dictionary<string, double> kq = new Dictionary<string, double>();
            string[] wordsUS = input.Split(' ');            //chia thành mảng từ không dấu
            Dictionary<string, double> words;               //danh sách từ có dấu từ 1 từ không dấu
            Dictionary<string, double> listWords;            //danh sách các câu có thể tạo thành từ từ ko dấu
            Dictionary<string, double> temp;                //danh sách tạm
            List<string> temp_word = new List<string>();
            bool isFirst = true;

            if (Data.P_One.ContainsKey(wordsUS[0]))
                words = Data.P_One[wordsUS[0]];
            else
            {
                words = new Dictionary<string, double>();
                words.Add(wordsUS[0], 1.0);
            }
            kq = words;
            temp_word.Add(wordsUS[0]);

            if (wordsUS.Length >= 2)
            {
                if (Data.P_One.ContainsKey(wordsUS[1]))
                    words = Data.P_One[wordsUS[1]];
                else
                {
                    words = new Dictionary<string, double>();
                    words.Add(wordsUS[1], 1.0);
                }
                temp_word.Add(wordsUS[1]);
                listWords = new Dictionary<string, double>();
                foreach (KeyValuePair<string, double> pair in kq)
                {
                    foreach (KeyValuePair<string, double> w in words)
                    {
                        listWords.Add(pair.Key + " " + w.Key, pair.Value);
                    }
                }
                temp = new Dictionary<string, double>();

                foreach (KeyValuePair<string, double> s in listWords)
                {
                    if (Data.P_Two.ContainsKey(Utils.processUtils.ConvertToUnSign(s.Key)))
                    {
                        if (Data.P_Two[Utils.processUtils.ConvertToUnSign(s.Key)].ContainsKey(s.Key))
                        {
                            temp.Add(s.Key, s.Value * Data.P_Two[Utils.processUtils.ConvertToUnSign(s.Key)][s.Key] * 1.0);
                        }
                        else
                        {
                            temp.Add(s.Key, s.Value * Data.ThresholdNotFound);
                        }
                    }
                    else
                    {
                        temp.Add(s.Key, s.Value * Data.ThresholdNotFound);
                    }
                }
                if (Data.AllowFilter)
                    kq = getRSForCount(temp, Data.ThresholdFilter);
                else
                    kq = temp;

                for (int i = 2; i < wordsUS.Length; i++)
                {
                    if (Data.P_One.ContainsKey(wordsUS[i]))
                        words = Data.P_One[wordsUS[i]];
                    else
                    {
                        words = new Dictionary<string, double>();
                        words.Add(wordsUS[i], Data.ThresholdNotFound);
                    }
                    temp_word.Add(wordsUS[i]);
                    if (isFirst == false)
                    {
                        temp_word.RemoveAt(0);
                    }
                    isFirst = false;
                    listWords = new Dictionary<string, double>();
                    foreach (KeyValuePair<string, double> pair in kq)
                    {
                        foreach (KeyValuePair<string, double> w in words)
                        {
                            listWords.Add(pair.Key + " " + w.Key, pair.Value * 1.0);
                        }
                    }
                    temp = new Dictionary<string, double>();
                    foreach (KeyValuePair<string, double> s in listWords)
                    {
                        if (Data.P_Three.ContainsKey(temp_word[0] + " " + temp_word[1] + " " + temp_word[2]))
                        {
                            string[] str = s.Key.Split(' ');
                            if (Data.P_Three[temp_word[0] + " " + temp_word[1] + " " + temp_word[2]].ContainsKey(str[str.Length - 3] + " " + str[str.Length - 2] + " " + str[str.Length - 1]))
                            {
                                temp.Add(s.Key, s.Value * Data.P_Three[temp_word[0] + " " + temp_word[1] + " " + temp_word[2]][str[str.Length - 3] + " " + str[str.Length - 2] + " " + str[str.Length - 1]] * 1.0);
                            }
                            else
                            {
                                temp.Add(s.Key, s.Value * Data.ThresholdNotFound);
                            }
                        }
                        else
                        {
                            temp.Add(s.Key, s.Value * Data.ThresholdNotFound);
                        }
                    }
                    if (Data.AllowFilter)
                        kq = getRSForCount(temp, Data.ThresholdFilter);
                    else
                        kq = temp;
                }
            }
            return getRS(kq);
        }
        public string getRS(Dictionary<string, double> rs)
        {
            try
            {
                double max = rs.Max(kvp => kvp.Value);
                return rs.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();
            }
            catch (Exception)
            {
                return null;
            }
        }
        public Dictionary<string, double> getRSForCount(Dictionary<string, double> RS, int count)
        {
            var items = from pair in RS
                        orderby pair.Value descending
                        select pair;
            Dictionary<string, double> rs = new Dictionary<string, double>();
            foreach (KeyValuePair<string, double> pair in items)
            {
                if (count == 0)
                    return rs;
                count--;
                rs.Add(pair.Key, pair.Value);
            }
            return rs;
        }
    }
}
